package tt.dz.order.util;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alibaba.druid.util.StringUtils;

/**
 * @title 微信支付工具类 当前逻辑主要使用此类
 * @author nibo
 */
@Component
public class WeiXinPayUtilBase {
	private static Logger log = LoggerFactory.getLogger(WeiXinPayUtilBase.class);

	public static final String RET_SUCCESS_XML = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

	public static final String RET_FAIL_XML = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";

	public static final String RET_SUCCESS_STR = "SUCCESS";

	public static final String RET_FAIL_STR = "FAIL";

	/** 微信支付退款接口地址 */
	private static final String WEIXIN_REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
	/** 微信统一下单地址 */
	public static final String WEIXIN_UNIFIEDORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";

	public static final String INPUT_CHARSET = "utf-8";

	/** 数据传输超时时间，默认为2秒钟 */
	private static int socketTimeout = 5 * 1000;

	/** 连接超时时间，默认为8秒钟 */
	private static int connectionTimeout = 8 * 1000;
	static Properties weiXinProperties = new Properties();

	static {
		try {
			InputStream in = new BufferedInputStream(WeiXinPayUtilBase.class.getResourceAsStream("/weixin.properties"));
			weiXinProperties.load(in);
		} catch (IOException e) {
			log.error(e.getMessage());
		}

	}

	/**
	 * 除去数组中的空值和签名参数
	 * 
	 * @param sArray
	 *            签名参数组
	 * @return 去掉空值与签名参数后的新签名参数组
	 */
	public static Map<String, String> paraFilter(Map<String, Object> sArray) {
		Map<String, String> result = new HashMap<String, String>();
		if (sArray == null || sArray.size() <= 0) {
			return result;
		}
		String key;
		String value = null;
		for (Entry<String, Object> entry : sArray.entrySet()) {
			key = entry.getKey();
			if (entry.getValue() != null) {
				value = entry.getValue().toString();
			}
			if (StringUtils.isEmpty(value) || "sign".equalsIgnoreCase(key) || "sign_type".equalsIgnoreCase(key)) {
				// 值为空或者key为"sign"的参数不进行拼接
				continue;
			}
			result.put(key, value);
		}
		// ci修改先保持原有逻辑,下个迭代删除2016/12/01
		// for (String key : sArray.keySet()) {
		// String value =sArray.get(key).toString();
		// if (value == null || value.equals("") || key.equalsIgnoreCase("sign")
		// || key.equalsIgnoreCase("sign_type")) {
		// // 值为空或者key为"sign"的参数不进行拼接
		// continue;
		// }
		// result.put(key, value);
		// }
		return result;
	}

	/**
	 * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
	 * 
	 * @param params
	 *            需要排序并参与字符拼接的参数组
	 * @return 拼接后字符串
	 */
	public static String createLinkString(Map<String, String> params) {
		List<String> keys = new ArrayList<String>(params.keySet());
		Collections.sort(keys);
		StringBuilder prestr = new StringBuilder();
		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			String value = params.get(key);
			if (i == keys.size() - 1) {// 拼接时，不包括最后一个&字符
				prestr = prestr.append(key).append("=").append(value);
			} else {
				prestr = prestr.append(key).append("=").append(value).append("&");
			}
		}
		return prestr.toString();
	}

	/**
	 * 微信支付回调验证sign签名
	 * 
	 * @param params
	 * @param htWeixinMchKey
	 *            商户
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static boolean verify(Map<String, Object> params, String htWeixinMchKey)
			throws UnsupportedEncodingException {
		String sign = (String) params.get("sign");
		if (sign == null) {
			log.error("微信支付回调验证sign签名,签名为空");
			return false;
		}
		// 过滤空值、sign与sign_type参数
		Map<String, String> sParaNew = paraFilter(params);
		// 拼接字符串
		String linkedStr = createLinkString(sParaNew);
		String preSignStr = new StringBuilder(linkedStr).append("&key=").append(htWeixinMchKey).toString();
		String signedStr = DigestUtils.md5Hex(preSignStr.getBytes(INPUT_CHARSET)).toUpperCase();
		return sign.equals(signedStr);
	}

	/**
	 * 微信支付生成sign签名
	 * 
	 * @return 签名字符串
	 */

	/**
	 * 微信支付生成sign签名
	 * 
	 * @param params
	 * @param weixinMchKey
	 *            商户秘钥
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String sign(Map<String, Object> params, String weixinMchKey) throws UnsupportedEncodingException {
		// 过滤空值、sign与sign_type参数
		Map<String, String> sParaNew = paraFilter(params);
		// 拼接字符串
		String linkedStr = createLinkString(sParaNew);
		String preSignStr = new StringBuilder(linkedStr).append("&key=").append(weixinMchKey).toString();
		return DigestUtils.md5Hex(preSignStr.getBytes(INPUT_CHARSET)).toUpperCase();
	}

	/**
	 * 微信支付退款发送https请求
	 * 
	 * @param params
	 */
	public static String sendRefundRequest(String paramXmlStr, SSLConnectionSocketFactory sslsf) {
		StringBuilder retXmlStr = new StringBuilder();
		CloseableHttpClient httpclient = null;
		CloseableHttpResponse response = null;
		try {
			httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
			HttpPost httpPost = new HttpPost(WEIXIN_REFUND_URL);
			// 设置请求和传输超时时间httpGet.setConfig(requestConfig);
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout)
					.setConnectTimeout(connectionTimeout).build();
			httpPost.setConfig(requestConfig);
			StringEntity strEntity = new StringEntity(paramXmlStr,
					ContentType.create("application/xml", INPUT_CHARSET));
			httpPost.setEntity(strEntity);
			response = httpclient.execute(httpPost);
			int responseStatus = response.getStatusLine().getStatusCode();
			if (responseStatus != HttpStatus.SC_OK) {
				log.error("微信支付退款发送https请求，响应状态不正确，responseStatus：" + responseStatus);
				return retXmlStr.toString();
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				InputStreamReader isr = new InputStreamReader(entity.getContent(), INPUT_CHARSET);
				BufferedReader bufferedReader = new BufferedReader(isr);
				String text;
				while ((text = bufferedReader.readLine()) != null) {
					retXmlStr.append(text);
				}
				bufferedReader.close();
				isr.close();
			}
			EntityUtils.consume(entity);
		} catch (UnsupportedEncodingException e) {
			log.error("微信支付退款发送https请求出错，" + e);
		} catch (UnsupportedOperationException e) {
			log.error("微信支付退款发送https请求出错，" + e);
		} catch (IOException e) {
			log.error("微信支付退款发送https请求出错，" + e);
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				if (httpclient != null) {
					httpclient.close();
				}
			} catch (IOException e) {
				log.error("微信支付退款发送https请求,关闭httpclient出错" + e);
			}
		}
		return retXmlStr.toString();
	}

	/**
	 * 根据key获取微信配置
	 * 
	 * @param key
	 * @return
	 */
	public static String getweiXinPropertieBykey(String key) {
		return weiXinProperties.getProperty(key);
	}
}